#include <string_view>

#include "ExtendDeviceManager10.h"
#include "GuiContext.h"
#include "CodeScanner.h"
#include "PowerMonitor.h"
#include "DoorAlertor.h"
#include "AcSwitchDetector.h"
#include "ConfigManager.h"
#include "CurrentVoltageManager.h"
#include "SpiChannel.h"


ExtendDeviceManager10::ExtendDeviceManager10() : IExtendDeviceManager(mouterCommunicator) , mextendHubChannel(ExtendHub::HUB_CHANNEL, mouterCommunicator), mextendHub(mextendHubChannel, ExtendDeviceEnum::EXTEND_HUB, ExtendDeviceEnum::EXTEND_HUB.name) {//
}

ExtendDeviceManager10::~ExtendDeviceManager10() {
    //dtor
}



void ExtendDeviceManager10::initialize() {
    SpiChannel::initSignalEnv();

    IExtendDeviceManager::initialize();

    IExtendDeviceManager::initial();

    DateTimeUtility::ClockTime_t triggerTime{(std::time(nullptr) + 6) * DateTimeUtility::ClockTime_t::period::den};
    TaskRecordPtr ptaskRecord(new TaskRecord(TaskletInfo{std::bind(&ExtendDeviceManager10::doUpdateInformation, this), nullptr}, triggerTime, tick_count_t(3 * DateTimeUtility::ClockTime_t::period::den), ETT_CIRCLE));

    TaskSchedulerSingleton::instance().addTask(ptaskRecord);
}


bool ExtendDeviceManager10::updateOnlineDevice(ChannelDevices& channelDevices) {
    DummyChannel& channel = *channelDevices.first;

    std::forward_list<ExtendDevicePtr>& deviceList = channelDevices.second;
    bool allDeviceOnline = true;
    bool deviceOnline;
    //  std::forward_list<ExtendDevicePtr>::iterator iterator =deviceList.begin();

    if (deviceList.empty()) {
        allDeviceOnline = false;
    } else {
        deviceList.remove_if([&allDeviceOnline, &deviceOnline, &channel](ExtendDevicePtr& pExtendDevicePtr) {
            deviceOnline = pExtendDevicePtr->recheck();
            LOG_DEDUG("%s,recheck:%d", channel.mexceptionTip.c_str(), deviceOnline);
//        if (deviceOnline){
//            ++allDeviceOnline;
//        }
            allDeviceOnline &= deviceOnline;
            return !deviceOnline;

        });

    }

    return allDeviceOnline;
}



bool ExtendDeviceManager10::doUpdateInformation() noexcept {
//    IExtendDeviceManager::initial();
//    return true;

//    ChannelDevices* pChannelDevices = nullptr;
    ExtendDevicePtr devicePtr;
    for (int i = 1; i < MDConst::DEFAULT_CHANNEL_COUNT; ++i) {//
/*        pChannelDevices = channelDevicesArray + i;
        for (ChannelDevices::second_type::iterator iterator = pChannelDevices->second.begin(); iterator != pChannelDevices->second.end(); ++iterator) {
            (*iterator)->activeUpdateInformation();
        }
        */
        devicePtr = mallOnlineDevice[i].lock();
        if (devicePtr){
            devicePtr->activeUpdateInformation();
        }
    }
    updateInnerDevice();

    return true;
}



bool ExtendDeviceManager10::doWork() {

    std::string prefix;
    ssize_t length = sizeof(mbuffer);

//    timespec time{2, 500 * 1000 * 1000};
    DeviceInfoHeader_t* pdeviceHeader = SpiChannel::waitAndRead(prefix, nullptr, mouterCommunicator, mbuffer, length);

    if (nullptr == pdeviceHeader || (1 > pdeviceHeader->channel || (4 < pdeviceHeader->channel && 255 > pdeviceHeader->channel)) || length < sizeof (DeviceInfoHeader_t)) {
        if (nullptr == pdeviceHeader) {//timeout
//           IExtendDeviceManager::initial();

            return true;
        }
        return true;
    }

    uint32_t channel = pdeviceHeader->channel;
    if (255 != channel) {
        static_cast <SpiChannel*>(&*channelDevicesArray[channel].first)->feedbackData(pdeviceHeader, length);
    } else {
        DeviceInfoHeader_t* subDeviceHeader = reinterpret_cast <DeviceInfoHeader_t*>(pdeviceHeader->payload);
        if (255 != subDeviceHeader->channel){
        ChannelDevices& channelDevices  = channelDevicesArray[subDeviceHeader->channel];
        std::string slaveData(reinterpret_cast <std::string::pointer>(subDeviceHeader->payload), length - (sizeof (DeviceInfoHeader_t) << 1));
//        printf("slaveData:%s,<WARN_OFFLINE> == slaveData:%d,<WARN_ERROR> == slaveData:%d\n", slaveData.data(), "<WARN_OFFLINE>" == slaveData, "<WARN_ERROR>" == slaveData);

        if (false == mnewOnlineDevice.empty()){
            mnewOnlineDevice.clear();
        }
        if ("<WARN_OFFLINE>" == slaveData || "<WARN_ERROR>" == slaveData) {
            channelDevices.second.clear();
        } else {
            bool found = false;
            for (ChannelDevices::second_type::iterator iterator = channelDevices.second.begin(); iterator != channelDevices.second.end(); ++iterator) {
                if ((*iterator)->matchDevice(*channelDevices.first, slaveData)) {
                    found = true;
                    break;
                }
            }

            if (!found) {
//                mnewOnlineDevice.clear();
                createAndAddExtendDevice(slaveData, channelDevices);
            }
        }

        if (!mnewOnlineDevice.empty()){
            Task* pTask = &mrefreshTask;
            mpool->pushPool(pTask);
        }
    } else {
        mextendHubChannel.feedbackData(subDeviceHeader, length - sizeof (DeviceInfoHeader_t));
    }
}

    return true;
}


